/**
 * @author: Miss.杨
 * @date: 2025年3月09日 20:12:49
 * @description: 
 */
package com.sheepone.monitor.handler;

import com.sheepone.monitor.codec.SheeponeContentDuplexConverter;
import com.sheepone.monitor.codec.SheeponePackage;
import com.sheepone.monitor.enums.SerializationAlgorithmsEnum;
import com.sheepone.monitor.enums.SheeponePackageTypeEnum;
import com.sheepone.webdev.log.WebDevLogger;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;

/**
 * @author: Miss.杨
 * @date: 2025年3月09日 20:12:49
 * @description:
 */
public abstract class AbstractSheeponeContentDuplexHandler<R, W> extends ChannelDuplexHandler
        implements SheeponeContentDuplexConverter<R, W> {
    private WebDevLogger logger = WebDevLogger.getLogger(AbstractSheeponeContentDuplexHandler.class);
    private SheeponePackageTypeEnum inType;
    private SheeponePackageTypeEnum outType;
    private SerializationAlgorithmsEnum outSerialization;

    public AbstractSheeponeContentDuplexHandler(SheeponePackageTypeEnum inType,
            SheeponePackageTypeEnum outType, SerializationAlgorithmsEnum outSerialization) {
        this.inType = inType;
        this.outType = outType;
        this.outSerialization = outSerialization;
    }

    protected abstract void channelRead0(ChannelHandlerContext ctx, R msg) throws Exception;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (!(msg instanceof SheeponePackage) || ((SheeponePackage) msg).getType() != inType) {
            ctx.fireChannelRead(msg);
            return;
        }
        SheeponePackage sp = (SheeponePackage) msg;
        if (sp.getType() != inType) {
            ctx.fireChannelRead(msg);
            return;
        }
        try {
            channelRead0(ctx, fromBytes(sp.getContent(), sp.getSerialization()));
        } catch (Exception e) {
            logger.error("{} channelRead error", this.getClass().getName(), e.getMessage());
        } finally {
            ctx.fireChannelRead(msg);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof SheeponePackage) {
            ctx.write(msg, promise);
            return;
        }
        Object obj = msg;
        try {
            W content = (W) msg;
            if (content != null) {
                SheeponePackage sp = new SheeponePackage();
                sp.setType(outType);
                sp.setSerialization(this.outSerialization);
                sp.setContent(toBytes(content, this.outSerialization));
                obj = sp;
            }
        } catch (Exception e) {
            if (!(e instanceof ClassCastException)) {
                logger.error("{} write error", this.getClass().getName(), e.getMessage());
            }
        } finally {
            ctx.write(obj, promise);
        }
    }
}
